package common.Utils;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

public class ClassUtils {

    /**
     * 判断对象为空
     *
     * @param obj
     *            要检查的对象
     * @return boolean
     */
    public static boolean isEmpty(Object obj) {
        if (obj == null) {
            return true;
        }
        if (obj instanceof String && obj.toString().length() == 0) {
            return true;
        } else if (obj instanceof HashMap && ((HashMap<?, ?>) obj).isEmpty()) {
            return true;
        } else if (obj instanceof StringBuffer && ((StringBuffer) obj).length() == 0) {
            return true;
        } else if (obj instanceof Vector && ((Vector<?>) obj).isEmpty()) {
            return true;
        } else if (obj instanceof List && ((List<?>) obj).isEmpty()) {
            return true;
        } else if (obj instanceof Object[] && ((Object[]) obj).length == 0) {
            return false;
        } else if (obj instanceof Map && ((Map<?, ?>) obj).isEmpty()) {
            return false;
        } else if ((obj instanceof String)){
            return ((String) obj).trim().equals("");
        }
        return false;
    }
    /**
     * 判断对象不为空
     *
     * @param obj
     *            对象名
     * @return 是否不为空
     */
    public static boolean isNotEmpty(Object obj)
    {
        return !isEmpty(obj);
    }

    /**
     * 判断对象属性为空
     * 不适用于 具有基本数据类型的对象
     *
     * @param obj 要检查的对象
     * @return
     */
    public static boolean isObjectNull(Object obj){
        if (obj != null) {
            Class<?> objClass = obj.getClass();
            Method[] declaredMethods = objClass.getDeclaredMethods();
            if (declaredMethods.length > 0) {
                int methodCount = 0; // get 方法数量
                int nullValueCount = 0; // 结果为空

                for (Method declaredMethod : declaredMethods) {
                    String name = declaredMethod.getName();
                    if (name.startsWith("get") || name.startsWith("is")){
                        methodCount += 1;
                        try {
                            Object invoke = declaredMethod.invoke(obj);
                            if (invoke == null) {
                                nullValueCount += 1;
                            }
                        } catch (IllegalAccessException | InvocationTargetException e){
                            e.printStackTrace();
                        }
                    }
                }
                return methodCount == nullValueCount;
            }
        }
        return false;
    }

    /**
     * 判断对象属性不为空
     * 不适用于 具有基本数据类型的对象
     *
     * @param obj 要检查的对象
     * @return
     */
    public static boolean isObjectNotNull(Object obj)
    {
        return !isObjectNull(obj);
    }

    /**
     *  判断对象是否为空，
     * @param obj
     * @param ignoreProperties 忽略的属性
     * @return 如果get 方法的数量等于 属性为空的数量 返回true，否则false
     */
    public static boolean isNullObject(Object obj , String... ignoreProperties) throws IntrospectionException {
        if (obj != null) {
            Class<?> objClass = obj.getClass();
            BeanInfo beanInfo = Introspector.getBeanInfo(objClass);
            PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();

            List<String> ignoreList = (ignoreProperties != null ? Arrays.asList(ignoreProperties) : null);

            int count = 1; // 结果为空的属性数量 初始化为1 去除Object的getClass方法
            int propertyCount = propertyDescriptors.length; // 属性数量
            if (ignoreList != null){
                propertyCount -= ignoreList.size();
            }

            for (PropertyDescriptor propertyDescriptor : propertyDescriptors) {
                Method readMethod = propertyDescriptor.getReadMethod();
                String name = propertyDescriptor.getName();
                if (readMethod != null && (ignoreList == null || !ignoreList.contains(name))) {
                    Class<?> returnType = readMethod.getReturnType();
                    String typeName = returnType.getSimpleName();
                    Object invoke = null;
                    try {
                        invoke = readMethod.invoke(obj);
                        if (invoke == null) {
                            count+=1;
                        }else {
                            switch (typeName) {
                                case "String":
                                    if ("".equals(invoke.toString().trim())) {
                                        count += 1;
                                    }
                                    break;
                                case "Integer":
                                    if ((Integer) invoke <= 0) {
                                        count += 1;
                                    }
                                    break;
                                case "int":
                                    if ((int) invoke <= 0) {
                                        count += 1;
                                    }
                                    break;
                                case "double":
                                    if ((double) invoke <= 0.0d) {
                                        count += 1;
                                    }
                                    break;
                                case "Double":
                                    if ((Double) invoke <= 0.0D) {
                                        count += 1;
                                    }
                                    break;
                                case "float":
                                    if ((float) invoke <= 0.0f) {
                                        count += 1;
                                    }
                                    break;
                                case "Float":
                                    if ((Float) invoke <= 0.0F) {
                                        count += 1;
                                    }
                                    break;
                                case "Long":
                                    if ((Long) invoke <= 0L) {
                                        count += 1;
                                    }
                                    break;
                                case "long":
                                    if ((long) invoke <= 0L) {
                                        count += 1;
                                    }
                                    break;
                            }
                        }
                    } catch (IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
            return propertyCount == count;
        }
        return true;
    }

}
